package org.example;

import org.apache.commons.lang.ClassUtils;
import org.apache.commons.lang.StringUtils;
import org.example.handler.MethodHandler;
import org.example.utils.ClassUtil;

import javax.servlet.ServletContext;
import javax.ws.rs.Path;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 上下文
 *
 * @author hrz
 * @since 2021/3/2 0002
 */
public class WebMvcContext {

    public static String CONTEXT_NAME = "WebMvcContext";

    /**
     * 请求路径和处理方法的映射关系集合
     */
    private Map<String, MethodHandler> pathMethodMappings = new HashMap<>();

    /**
     * 根据请求路径匹配执行的方法
     *
     * @param url 请求路径
     * @return 处理请求的方法
     */
    public MethodHandler match(String url) {
        return pathMethodMappings.get(url);
    }

    public void init(ServletContext servletContext, String basePackage) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        System.out.println("MVC上下文开始初始化。。。。");
        List<Class<?>> classes = ClassUtil.getClasses(basePackage);
        for (Class<?> aClass : classes) {
            Method[] methods = aClass.getDeclaredMethods();
            String path = null;
            for (Method method : methods) {
                Path pathAnnotation = method.getAnnotation(Path.class);
                if (pathAnnotation == null) {
                    // 如果没有Path注解标记，跳过
                    continue;
                }

                // 拼接请求url
                if (StringUtils.isEmpty(pathAnnotation.value())) {
                    path = servletContext.getContextPath() + "/" + method.getName();
                } else {
                    if (pathAnnotation.value().startsWith("/")) {
                        path = servletContext.getContextPath() + pathAnnotation.value();
                    } else {
                        path = servletContext.getContextPath() + "/" + pathAnnotation.value();
                    }
                }

                // 实例化当前类
                Object newInstance = aClass.newInstance();
                pathMethodMappings.put(path, new MethodHandler(method, newInstance, path));
            }
        }
        System.out.println("MVC上下文结束初始化。。。。");
    }
}
